package com.easylinkin.linkappapi.lobar.util;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.easylinkin.linkappapi.lobar.dto.UserProjectDTO;
import com.easylinkin.linkappapi.lobar.entity.Group;
import com.easylinkin.linkappapi.lobar.entity.UserRecord;
import com.easylinkin.linkappapi.lobar.entity.UserStatistics;
import com.easylinkin.linkappapi.lobar.mapper.GroupMapper;
import com.easylinkin.linkappapi.lobar.mapper.UserProjectMapper;
import com.easylinkin.linkappapi.lobar.mapper.UserRecordMapper;
import com.easylinkin.linkappapi.lobar.mapper.UserStatisticsMapper;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.tenant.entity.LinkappTenant;
import com.easylinkin.linkappapi.tenant.mapper.LinkappTenantMapper;

import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
 * @Author: kan yuanfeng
 * @Date: 2022/4/24 14:37
 * @Description:
 */
@Component
public class UserClockTimer {

  @Autowired
  private LinkappTenantMapper linkappTenantMapper;
  @Autowired
  private UserProjectMapper userProjectMapper;
  @Autowired
  private UserRecordMapper userRecordMapper;
  @Autowired
  private UserStatisticsMapper userStatisticsMapper;
  @Autowired
  private GroupMapper groupMapper;
  @Autowired
  private LinkappUserContextProducer linkappUserContextProducer;

  private static final Logger LOGGER = org.slf4j.LoggerFactory.getLogger(UserClockTimer.class);

  @Scheduled(cron = "0 3 2 * * ?")
  public void countClock(){
    try {
      LOGGER.info("考勤汇总定时任务开始==================================================");
      //统计前几天没有统计的考勤数据
      List<LinkappTenant> list = linkappTenantMapper.selectByProjectId(null);
      list.removeIf(l -> "1".equals(l.getId()));
      //采取多线程处理  现网太慢了
      ExecutorService threadPool = Executors.newFixedThreadPool(20);
      list.forEach(l ->
        threadPool.submit(() ->{
            countHandler(l);
        })
      );
      LOGGER.info("考勤汇总定时任务结束==================================================");
    }catch (Exception e){
      LOGGER.error("考勤汇总定时任务异常==================================================",e);
    }
  }

    /**
     * 统计处理
     * @param l
     */
    private void countHandler(LinkappTenant l) {
        //查询考勤数据
        //查询最新统计的时间
        Date time = userStatisticsMapper.selectMaxTime(l.getId());
        if (null == time){
            time = DateUtil.beginOfDay(DateUtil.yesterday());
        }
        //查询所有人员数据
        List<UserProjectDTO> userProjects = userProjectMapper.selectAll(l.getId());
        //查询所有班组
        QueryWrapper<Group> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status_",1).eq("tenant_id_", l.getId());
        List<Group> tGroup = groupMapper.selectList(queryWrapper);

        //查询人员考勤数据
        List<UserRecord> userRecords = userRecordMapper.selectAll(l.getId(),time);
        //update 20221019 去掉当天的考勤
        userRecords.removeIf(u->DateUtil.beginOfDay(new Date()).getTime() == u.getRecordTime().getTime());
        //记录没有缺勤的
        toHandlerRecords(userProjects,userRecords);
        //过滤掉已经记录的
        Map<Date, List<UserRecord>> listMap = userRecords.stream()
                .collect(Collectors.groupingBy(r -> r.getRecordTime()));
        //包不包含昨天
        isContainsYesTerday(listMap);
        listMap.forEach((k,v) ->{
          //按班组分组
          Map<String, List<UserProjectDTO>> userMap = userProjects.stream()
                  .collect(Collectors.groupingBy(c -> c.getGroupId()));
          //包不包含所有班组
          isContainsAllGroup(userMap,tGroup);
          userMap.forEach((key,value) ->{
            UserStatistics userStatistics = new UserStatistics();
            //统计人数
            userStatistics.setTenantId(l.getId());
            userStatistics.setRecordTime(k);
            //按班组过滤考勤记录
            List<UserRecord> cRecordList = v.stream()
                    .filter(item -> key.equals(item.getGroupId()) && !Integer.valueOf(0).equals(item.getRecordType()))
                    .collect(Collectors.toList());
            userStatistics.setSum(value.size());
            //管理人员
//            int size = value.stream().filter(c -> "1".equals(c.getType())).collect(Collectors.toList())
//                .size();
            int size = value.stream()
                    .filter(c -> StringUtils.isNotBlank(c.getWorkType()) && c.getWorkType().startsWith("管理人员"))
                    .collect(Collectors.toList())
                    .size();
            userStatistics.setManage(size);
            //劳务人员
            if (value.size()<1){
              List<String> list1 = tGroup.stream().filter(t -> key.equals(t.getId()))
                      .map(t -> t.getCompanyProjectId()).collect(Collectors.toList());
              userStatistics.setCompanyProjectId(list1.get(0));
            }else {
              userStatistics.setCompanyProjectId(value.get(0).getCompanyProjectId());
            }
            userStatistics.setGroupId(key);
            userStatistics.setWork(value.size()-size);
            userStatistics.setOn(cRecordList.size());
            userStatistics.setOff((value.size()-cRecordList.size())>0?(value.size()-cRecordList.size()):0);
            userStatistics.setHours(cRecordList.stream().mapToDouble(r -> r.getHour()).sum());
            userStatistics.setType(cRecordList.size()>0?cRecordList.get(0).getType():2);
            userStatistics.setCreateTime(new Date());
            userStatisticsMapper.insert(userStatistics);
          });
        });
    }

    /**
   * //包不包含所有班组
   * @param userMap
   * @param tGroup
   */
  private void isContainsAllGroup(Map<String, List<UserProjectDTO>> userMap, List<Group> tGroup) {
    tGroup.forEach(t->{
      if (!userMap.containsKey(t.getId())){
        userMap.put(t.getId(),new ArrayList<>());
      }
    });
  }

  /**
   * 是否包含昨天的记录，不包含的话新增昨天的记录
   * @param listMap
   */
  private void isContainsYesTerday(Map<Date, List<UserRecord>> listMap) {
    Date dateTime = DateUtil.beginOfDay(DateUtil.yesterday());
    if (!listMap.containsKey(dateTime)){
      listMap.put(dateTime,new ArrayList<>());
    }
  }

  /**
   * 记录缺勤人员
   * @param userProjects
   * @param userRecords
   */
  private void toHandlerRecords(List<UserProjectDTO> userProjects, List<UserRecord> userRecords) {
//    List<UserProjectDTO> userProjectDTOS = userProjects.stream().filter(u -> tenantId.equals(u.getTenantId()))
//        .collect(Collectors.toList());
    //过滤掉已经记录的
//    List<UserRecord> recordList1 = userRecords.stream()
//        .filter(u -> tenantId.equals(u.getTenantId()) && !dates.contains(u.getRecordTime()))
//        .collect(Collectors.toList());

    Map<Date, List<UserRecord>> listMap = userRecords.stream()
        .collect(Collectors.groupingBy(r -> r.getRecordTime()));
    //包不包含昨天
    isContainsYesTerday(listMap);
    listMap.forEach((key,value) ->{
      //去掉已经记录的
      Set<String> userIds = value.stream().map(v -> v.getUserId()).collect(Collectors.toSet());
      List<UserProjectDTO> newList = BeanUtil
          .copyToList(userProjects, UserProjectDTO.class);
      newList.removeIf(u->userIds.contains(u.getUserId()));
      newList.forEach(u ->{
        UserRecord userRecord = new UserRecord();
        BeanUtils.copyProperties(u,userRecord);
        userRecord.setUserId(u.getUserId());
        userRecord.setType(2);
        userRecord.setHour(0d);
        userRecord.setRecordType(0);
        userRecord.setModifyTime(new Date());
        userRecord.setCreateTime(new Date());
        userRecord.setRecordTime(key);
        userRecordMapper.insert(userRecord);
      });
    });
  }


  /**
   * 手动触发定时任务
   * type = 1 表示触发所有项目
   * 为空  本项目
   */
  public void countClock(Integer type, Date date) {
    LOGGER.info("考勤汇总定时任务开始==================================================");
    //统计前几天没有统计的考勤数据
    List<LinkappTenant> list = linkappTenantMapper.selectByProjectId(null);
    list.removeIf(l -> "1".equals(l.getId()));
    if (null == type){
      list.removeIf(l->!l.getId().equals(linkappUserContextProducer.getNotNullCurrent().getTenantId()));
    }
    //采取多线程处理  现网太慢了
    ExecutorService threadPool = Executors.newFixedThreadPool(20);
    list.forEach(l ->
      threadPool.submit(() ->{
          countHandlerTest(date, l);
//          countHandler(l);
      })
    );
    LOGGER.info("考勤汇总定时任务结束==================================================");
//    //查询考勤数据
//    QueryWrapper<UserStatistics> queryWrapper1 = new QueryWrapper<>();
//    if (null == type) {
//      String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
//      queryWrapper1.eq("tenant_id_",tenantId);
//    }
//    List<UserStatistics> selectList = userStatisticsMapper.selectList(queryWrapper1);
//    List<Date> dates = selectList.stream().map(s -> s.getRecordTime())
//        .collect(Collectors.toList());
//    //查询所有人员数据
//    List<UserProjectDTO> userProjects = userProjectMapper.selectAll();
//    //查询所有班组
//    QueryWrapper<Group> queryWrapper = new QueryWrapper<>();
//    queryWrapper.eq("status_",1);
//    List<Group> groupList = groupMapper.selectList(queryWrapper);
//
//    //查询人员考勤数据
//    List<UserRecord> userRecords = userRecordMapper.selectAll();
//    //update 20221019 去掉当天的考勤
//    userRecords.removeIf(u->DateUtil.beginOfDay(new Date()).getTime() == u.getRecordTime().getTime());
//    //统计前几天没有统计的考勤数据
//    if (null != date){
//      userRecords.removeIf(u->DateUtil.beginOfDay(date).getTime() != u.getRecordTime().getTime());
//    }
//    List<LinkappTenant> list = linkappTenantMapper.selectByProjectId(null);
//    list.removeIf(l -> "1".equals(l.getId()));
//    if (null == type){
//      list.removeIf(l->!l.getId().equals(linkappUserContextProducer.getNotNullCurrent().getTenantId()));
//    }
//    //采取多线程处理  现网太慢了
//    ExecutorService threadPool = Executors.newFixedThreadPool(20);
//    list.forEach(l ->{
//      threadPool.submit(() ->{
//        //过滤分组
//        List<Group> tGroup = groupList.stream().filter(g -> l.getId().equals(g.getTenantId()))
//                .collect(Collectors.toList());
//        //记录没有缺勤的
//        toHandlerRecords(l.getId(),dates,userProjects,userRecords);
//        //过滤掉已经记录的
//        List<UserRecord> recordList1 = userRecords.stream()
//                .filter(u -> l.getId().equals(u.getTenantId()) && !dates.contains(u.getRecordTime()))
//                .collect(Collectors.toList());
//        Map<Date, List<UserRecord>> listMap = recordList1.stream()
//                .collect(Collectors.groupingBy(r -> r.getRecordTime()));
//        //包不包含昨天
//        isContainsYesTerday(listMap);
//        listMap.forEach((k,v) ->{
//          List<UserProjectDTO> collect = userProjects.stream()
//                  .filter(user -> l.getId().equals(user.getTenantId())).collect(Collectors.toList());
//          //按班组分组
//          Map<String, List<UserProjectDTO>> userMap = collect.stream()
//                  .collect(Collectors.groupingBy(c -> c.getGroupId()));
//          //包不包含所有班组
//          isContainsAllGroup(userMap,tGroup);
//          userMap.forEach((key,value) ->{
//            UserStatistics userStatistics = new UserStatistics();
//            //统计人数
//            userStatistics.setTenantId(l.getId());
//            userStatistics.setRecordTime(k);
//            //按班组过滤考勤记录
//            List<UserRecord> cRecordList = v.stream()
//                    .filter(item -> key.equals(item.getGroupId())).collect(Collectors.toList());
//            userStatistics.setSum(value.size());
//            //管理人员
//            int size = value.stream().filter(c -> "1".equals(c.getType())).collect(Collectors.toList())
//                    .size();
//            userStatistics.setManage(size);
//            //劳务人员
//            if (value.size()<1){
//              List<String> list1 = tGroup.stream().filter(t -> key.equals(t.getId()))
//                      .map(t -> t.getCompanyProjectId()).collect(Collectors.toList());
//              userStatistics.setCompanyProjectId(list1.get(0));
//            }else {
//              userStatistics.setCompanyProjectId(value.get(0).getCompanyProjectId());
//            }
//            userStatistics.setGroupId(key);
//            userStatistics.setWork(value.size()-size);
//            userStatistics.setOn(cRecordList.size());
//            userStatistics.setOff((value.size()-cRecordList.size())>0?(value.size()-cRecordList.size()):0);
//            userStatistics.setHours(cRecordList.stream().mapToDouble(r -> r.getHour()).sum());
//            userStatistics.setType(cRecordList.size()>0?cRecordList.get(0).getType():2);
//            userStatistics.setCreateTime(new Date());
//            userStatisticsMapper.insert(userStatistics);
//          });
//        });
//      });
//    });
    LOGGER.info("考勤汇总定时任务结束==================================================");
  }

    private void countHandlerTest(Date date, LinkappTenant l) {
        //查询考勤数据
        QueryWrapper<UserStatistics> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.select("record_time_","tenant_id_").eq("tenant_id_", l.getId());
        List<UserStatistics> selectList = userStatisticsMapper.selectList(objectQueryWrapper);
        List<Date> dates = selectList.stream().map(s -> s.getRecordTime())
                .collect(Collectors.toList());
        //查询所有人员数据
        List<UserProjectDTO> userProjects = userProjectMapper.selectAll(l.getId());
        //查询所有班组
        QueryWrapper<Group> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status_",1).eq("tenant_id_", l.getId());
        List<Group> tGroup = groupMapper.selectList(queryWrapper);
        List<UserRecord> userRecords = new ArrayList<>();
        //查询人员考勤数据
        if (null != date){
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.DATE,-1);
            userRecords = userRecordMapper.selectAll(l.getId(),calendar.getTime());
        }else {
            userRecords = userRecordMapper.selectAll(l.getId(),null);
        }
        //update 20221019 去掉当天的考勤
        userRecords.removeIf(u->DateUtil.beginOfDay(new Date()).getTime() == u.getRecordTime().getTime());
        //统计前几天没有统计的考勤数据
        if (null != date){
          userRecords.removeIf(u->DateUtil.beginOfDay(date).getTime() != u.getRecordTime().getTime());
        }
        //过滤分组
//          List<Group> tGroup = groupList.stream().filter(g -> l.getId().equals(g.getTenantId()))
//                  .collect(Collectors.toList());
        List<UserRecord> recordList1 = userRecords.stream()
                .filter(u -> !dates.contains(u.getRecordTime()))
                .collect(Collectors.toList());
        //记录没有缺勤的
        toHandlerRecords(userProjects,recordList1);
        //过滤掉已经记录的
        Map<Date, List<UserRecord>> listMap = recordList1.stream()
                .collect(Collectors.groupingBy(r -> r.getRecordTime()));
        //包不包含昨天
        isContainsYesTerday(listMap);
        listMap.forEach((k,v) ->{
          //按班组分组
          Map<String, List<UserProjectDTO>> userMap = userProjects.stream()
                  .collect(Collectors.groupingBy(c -> c.getGroupId()));
          //包不包含所有班组
          isContainsAllGroup(userMap,tGroup);
          userMap.forEach((key,value) ->{
            UserStatistics userStatistics = new UserStatistics();
            //统计人数
            userStatistics.setTenantId(l.getId());
            userStatistics.setRecordTime(k);
            //按班组过滤考勤记录
            List<UserRecord> cRecordList = v.stream()
                    .filter(item -> key.equals(item.getGroupId()) && !Integer.valueOf(0).equals(item.getRecordType()))
                    .collect(Collectors.toList());
            userStatistics.setSum(value.size());
            //管理人员
//            int size = value.stream().filter(c -> "1".equals(c.getType())).collect(Collectors.toList())
//                .size();
            int size = value.stream()
                    .filter(c -> StringUtils.isNotBlank(c.getWorkType()) && c.getWorkType().startsWith("管理人员"))
                    .collect(Collectors.toList())
                    .size();
            userStatistics.setManage(size);
            //劳务人员
            if (value.size()<1){
              List<String> list1 = tGroup.stream().filter(t -> key.equals(t.getId()))
                      .map(t -> t.getCompanyProjectId()).collect(Collectors.toList());
              userStatistics.setCompanyProjectId(list1.get(0));
            }else {
              userStatistics.setCompanyProjectId(value.get(0).getCompanyProjectId());
            }
            userStatistics.setGroupId(key);
            userStatistics.setWork(value.size()-size);
            userStatistics.setOn(cRecordList.size());
            userStatistics.setOff((value.size()-cRecordList.size())>0?(value.size()-cRecordList.size()):0);
            userStatistics.setHours(cRecordList.stream().mapToDouble(r -> r.getHour()).sum());
            userStatistics.setType(cRecordList.size()>0?cRecordList.get(0).getType():2);
            userStatistics.setCreateTime(new Date());
            userStatisticsMapper.insert(userStatistics);
          });
        });
    }
}
